// Kony

#pragma once

#include "CoreMinimal.h"
#include "Character/BaseCharacter.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Interaction/PlayerInterface.h"
#include "Interaction/TargetInterface.h"
#include "UI/WidgetController/OverlayWidgetController.h"
#include "PlayerCharacter.generated.h" //必须放最后！

class UNiagaraComponent;
/**
 * 玩家角色类
 */
UCLASS()
class GASC_HUANLING_API APlayerCharacter : public ABaseCharacter , public IPlayerInterface, public ITargetInterface
{
	GENERATED_BODY()
public:
	APlayerCharacter();
	//这个是为了初始化角色能力系统，由于属性集是在PlayerState中,
	//所以要在PossessedBy中调用InitAbilityActorInfo初始化把BasePlayerState属性数据 赋值给PlayerCharacter 角色
	//这是服务端
	virtual void PossessedBy(AController* NewController) override;
	//这是客户端
	virtual void OnRep_PlayerState() override;
	//加载角色存档进度
	void LoadProgress();
	/** Player Interface 玩家接口 */
	//重写存储玩家进度函数
	virtual void SaveProgress_Implementation(const FName& CheckpointTag) override;
	//重写获取升级所需经验值
	virtual int32 FindLevelForLevelAndXP_Implementation(int32 InLevel, int32 InXP) const override;
	//重写获取修为值接口实现
	virtual int32 GetXP_Implementation() const override;
	//重写写入修为值接口实现
	virtual void AddToXP_Implementation(int32 InXP) override;
	//重写获取属性点/修炼点数接口实现
	virtual int32 GetAttributePointsReward_Implementation(int32 Level) const override;
	//重写获取技能点/修为点数接口实现
	virtual int32 GetSpellPointsReward_Implementation(int32 Level) const override;
	//重写增加玩家等级接口实现
	virtual void AddToPlayerLevel_Implementation(int32 InPlayerLevel) override;
	//重写增加玩家属性点/修炼点数接口实现
	virtual void AddToAttributePoints_Implementation(int32 InAttributePoints) override;
	//重写获取当前玩家可用属性点/修炼点数接口实现
	virtual int32 GetAttributePoints_Implementation() const override;
	//重写增加玩家技能点/修为点数接口实现
	virtual void AddToSpellPoints_Implementation(int32 InSpellPoints) override;
	//重写获取当前玩家可用技能点/修为点数接口实现
	virtual int32 GetSpellPoints_Implementation() const override;
	//重写获取灵气值接口实现
	virtual int32 GetLingQi_Implementation() const override;
	//重写写入灵气值接口实现
	virtual void AddToLingQi_Implementation(int32 InLingQi) override;
	//重写获取等级接口实现
	virtual int32 GetLevel_Implementation() const override;
	//重写升级接口实现
	virtual void LevelUp_Implementation() override;

	//重写设置选中目标接口实现
	virtual void SetSelectedTarget_Implementation(AActor* InSelectedTarget) override;
	//重写获取选中目标接口实现
	virtual AActor* GetSelectedTarget_Implementation() const override;
	//重写清除选中目标接口实现
	virtual void ClearSelectedTarget_Implementation() override;

	//重写显示鼠标魔法阵
	virtual void ShowMagicCircle_Implementation(UMaterialInstance* DecalMaterial = nullptr, FGameplayTag SpellInputTag = FGameplayTag()) override;
	//重写隐藏鼠标魔法阵
	virtual void HideMagicCircle_Implementation() override;
	
	/** end Player Interface */

	
	
	/** Combat Interface 玩家接口 */
	virtual int32 GetPlayerLevel_Implementation() override;
	virtual void Die(const FVector& DeathImpulse) override;
	//设置战斗锁定目标
	virtual void SetCombatTarget_Implementation(AActor* InCombatTarget) override;
	virtual AActor* GetCombatTarget_Implementation() const override;
	/** end Combat Interface */

	/** Target Interface 目标接口 */
	virtual void HighlightActor_Implementation() override; //重写接口抽象类 设置高亮
	virtual void UnHighlightActor_Implementation() override; //重写接口抽象类 取消高亮
	virtual void SetMoveToLocation_Implementation(FVector& OutDestination) override; //重写缓存目的地接口
	/** end Target Interface */

	//玩家升级Niagara效果组件
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	TObjectPtr<UNiagaraComponent> LevelUpNiagaraComponent;
	

	/** 新增属性 需要修改这里 增加广播委托事件 **/
	//广播生命值变化事件
	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChangedSignature OnHealthChanged;

	//广播最大生命值变化事件
	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChangedSignature OnMaxHealthChanged;

	//广播法力值变化事件
	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChangedSignature OnManaChanged;

	//广播最大法力值变化事件
	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChangedSignature OnMaxManaChanged;

	/** Returns TopDownCameraComponent subobject **/
	FORCEINLINE class UCameraComponent* GetTopDownCameraComponent() const { return TopDownCameraComponent; }
	/** Returns CameraBoom subobject **/
	FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

	//复制需要动画的异常状态给客户端
	virtual void OnRep_Burned() override;
	virtual void OnRep_Stunned() override;
	virtual void OnRep_Downed() override;

	//异常状态 禁止输入按键函数
	void DisablPlayerInput(int32 DisableInputType);

	
	
private:
	//继承自父类 初始化能力系统 用于获取AbilitySystemComponent
	virtual void InitAbilityActorInfo() override;

	/** 用于把客户端选择同步到服务端的RPC */
	UFUNCTION(Server, Reliable)
	void ServerSetSelectedTarget(AActor* InSelectedTarget);

	//多播 RPC 复制给其他客户端，让其他玩家也看到这个玩家的升级特效
	UFUNCTION(NetMulticast, Reliable)
	void MulticastLevelUpParticles() const;
	
	// 绑定属性变化委托
	void BindAttributeChangeDelegates();
	
	// 广播初始属性值
	void BroadcastInitialValues();
	bool bBroadcastAttribute = false;
	/** Top down camera */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class UCameraComponent* TopDownCameraComponent;

	/** Camera boom positioning the camera above the character */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class USpringArmComponent* CameraBoom;
protected:
	virtual void BeginPlay() override;
	
	// //弹簧臂 c++ 实现是为了解决5.3.2无法像课程那样使用蓝图建立 会导致SpringArm 无法根据定位
	// UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	// TObjectPtr<USpringArmComponent> SpringArmComponent;
	// //相机
	// UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
	// TObjectPtr<UCameraComponent> CameraComponent;


	
};
